﻿using Microsoft.IdentityModel.Tokens;
using NETCore.Encrypt;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using WucCloud.Database;
using WucCloud.Entity;
using WucCloud.Utility;

namespace WucCloud.Application
{
    /// <summary>
    /// 用户服务
    /// </summary>
    public class UserInfoService :BaseService<UserInfoEntity>,IDependency
    {
        /// <summary>
        /// 子类构造函数
        /// </summary>
        /// <param name="userRepository"></param>
        public UserInfoService(IBaseRepository<UserInfoEntity> userRepository, IUnitOfWork unitOfWork)
        {
            base._repository = userRepository;
            base._unitOfWork = unitOfWork;
        }

        #region 获取数据
        /// <summary>
        /// 通过Id查询
        /// </summary>
        /// <param name="keyId">主键Id</param>
        /// <returns></returns>
        public async Task<UserInfoEntity> FindById(string keyId)
        {
            try
            {
                //通过Id查询用户数据
                var entity = await _repository.FindByIdAsync(keyId);
                return entity;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }            
        }

        /// <summary>
        /// 自定义条件查询
        /// </summary>
        /// <param name="keyvalue">查询条件(编码/姓名)</param>
        /// <returns></returns>
        public async Task<List<UserInfoEntity>> GetList(string keyvalue)
        {
            try
            {
                var entity = await _repository.QueryableAsync(t => t.IsEnabled == true && t.IsDeleted == false);
                //条件查询 根据编码/姓名查询
                if (!string.IsNullOrEmpty(keyvalue))
                {
                    entity = entity.FindAll(t => t.EnCode.Contains(keyvalue) || t.RealName.Contains(keyvalue));
                }
                return entity;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }           
        }

        /// <summary>
        /// 自定义条件分页查询
        /// </summary>
        /// <param name="keyvalue">查询条件(编码/姓名)</param>
        /// <param name="page">分页组件类</param>
        /// <returns></returns>
        public async Task<List<UserInfoEntity>> QueryPagedList(string keyvalue, PageModel page)
        {
            try
            {
                //获取未锁定账户的用户分页数据
                var entity = await _repository.SugarQueryable()
                    .Where(t => t.IsEnabled == true && t.IsDeleted == false)
                    .ToOffsetPageAsync(page.PageIndex, page.PageSize);

                //条件查询 根据编码/姓名查询
                if (!string.IsNullOrEmpty(keyvalue))
                {
                    entity = entity.FindAll(t => t.EnCode.Contains(keyvalue) || t.RealName.Contains(keyvalue));
                }

                return entity;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }            
        }
        #endregion

        #region 提交数据
        /// <summary>
        /// 保存数据（新增/编辑）
        /// </summary>
        /// <param name="keyId">主键Id</param>
        /// <param name="entity">实体信息</param>
        /// <returns></returns>
        public async Task<bool> SaveChange(string keyId,UserInfoEntity entity)
        {
            try
            {
                //新增
                if (string.IsNullOrEmpty(keyId))
                {
                    #region 数据校验
                    var data = await _repository.AnyAsync(t => t.AccountName == entity.AccountName);
                    if (data == true)
                    {
                        throw new Exception("账户已存在，请重新输入");
                    }
                    //非空校验
                    if (string.IsNullOrEmpty(entity.EnCode) || string.IsNullOrEmpty(entity.AccountName) || string.IsNullOrEmpty(entity.Password) || string.IsNullOrEmpty(entity.RealName) || string.IsNullOrEmpty(entity.MobilePhone))
                    {
                        throw new Exception("编码/账户/密码/真实姓名/手机号不可为空");
                    }
                    #endregion

                    //数据初始化
                    entity.KeyId = IDGenerator.CreateNewId();
                    entity.Password = EncryptProvider.Md5(entity.Password).ToLower();
                    entity.IsEnabled = true;
                    entity.IsDeleted = false;
                    entity.IsAdmin = false;
                    entity.CreateTime = DateTime.Now;
                    entity.CreateUserId = GlobalContext.CurrentUser().KeyId;
                    entity.CreateUserName = GlobalContext.CurrentUser().RealName;

                    return await _repository.InsertAsync(entity);
                }
                //编辑
                else
                {
                    //数据初始化
                    entity.KeyId = keyId;
                    entity.Password = EncryptProvider.Md5(entity.Password).ToLower();
                    entity.IsEnabled = true;
                    entity.IsDeleted = false;
                    entity.UpdateTime = DateTime.Now;
                    entity.UpdateUserId = GlobalContext.CurrentUser().KeyId;
                    entity.UpdateUserName = GlobalContext.CurrentUser().RealName;

                    return await _repository.UpdateAsync(entity);
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }            
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="keyId">主键Id</param>
        /// <returns></returns>
        public async Task<bool> Deleteable(string keyId)
        {
            try
            {
                bool result = await _repository.DeleteAsync(keyId);
                if (!result)
                {
                    throw new Exception("删除失败");
                }
                return result;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }           
        }

        /// <summary>
        /// 假删（逻辑删除）
        /// </summary>
        /// <param name="keyId"></param>
        /// <returns></returns>
        public async Task<bool> SoftDeleteable(string keyId)
        {
            try
            {
                var data = await _repository.FindByIdAsync(keyId);
                data.IsEnabled = false;
                data.IsDeleted = true;
                bool result = await _repository.UpdateAsync(data);
                if (!result)
                {
                    throw new Exception("删除失败");
                }
                return result;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="keyIds">主键Id集合,以英文逗号分隔</param>
        /// <returns></returns>
        public async Task<bool> BatchDeleteable(string[] keyIds)
        {
            try
            {
                bool result = false;
                //将数组转换为以,分割的字符串
                string Ids = string.Join(",", keyIds);
                foreach (var item in Ids.Split(','))
                {
                    result = await _repository.DeleteAsync(item);
                }
                if (!result)
                {
                    throw new Exception("删除失败");
                }
                else
                {
                    return result;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }
        }

        /// <summary>
        /// 修改密码（新旧密码）
        /// </summary>
        /// <param name="keyId">主键Id</param>
        /// <param name="oldPwd">原密码</param>
        /// <param name="newPwd">新密码</param>
        /// <returns></returns>
        public async Task<bool> UpdateablePwd(string keyId, string oldPwd, string newPwd)
        {
            try
            {
                var data = await _repository.FindByIdAsync(keyId);

                //对输入的原密码 进行Md5加密
                string pwd = EncryptProvider.Md5(oldPwd).ToLower();

                //原密码与数据库密码进行校验
                if (data.Password != pwd)
                {
                    throw new Exception("原密码输入错误");
                }
                else
                {
                    data.Password = EncryptProvider.Md5(newPwd).ToLower();
                    bool result = await _repository.UpdateAsync(data);
                    if (!result)
                    {
                        throw new Exception("编辑失败");
                    }
                    else
                    {
                        return result;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }
        }

        /// <summary>
        /// 锁定账户
        /// </summary>
        /// <param name="keyId">主键Id</param>
        /// <returns></returns>
        public async Task<bool> LockAccount(string keyId)
        {
            try
            {
                var data = await _repository.FindByIdAsync(keyId);
                if (data == null)
                {
                    throw new Exception("请选中要锁定的用户数据");
                }
                else
                {
                    data.IsLock = false;
                    bool result = await _repository.UpdateAsync(data);
                    if (!result)
                    {
                        throw new Exception("操作失败");
                    }
                    else
                    {
                        return result;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }
        }

        /// <summary>
        /// 解锁账户
        /// </summary>
        /// <param name="keyId">主键Id</param>
        /// <returns></returns>
        public async Task<bool> UnLockAccount(string keyId)
        {
            try
            {
                var data = await _repository.FindByIdAsync(keyId);
                if (data == null)
                {
                    throw new Exception("请选中要解锁的用户数据");
                }
                else
                {
                    data.IsLock = true;
                    bool result = await _repository.UpdateAsync(data);
                    if (!result)
                    {
                        throw new Exception("操作失败");
                    }
                    else
                    {
                        return result;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }
        }
        #endregion

        #region 拓展
        /// <summary>
        /// 登录 获取Token令牌
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<string> CheckSign(string userName, string password)
        {
            try
            {
                var entity = await _repository.FindAsync(t => t.AccountName == userName);
                var roleCode = await GetUserRoleName(userName,password);
                if (entity != null)
                {
                    if (entity.IsEnabled == true && entity.IsLock == false)
                    {
                        //对输入的密码进行Md5加密
                        var pwd = EncryptProvider.Md5(password).ToLower();
                        if (entity.Password == pwd)
                        {
                            string jwtStr = string.Empty;
                            
                            //登录成功 操作
                            TokenModel token = new TokenModel
                            {
                                UserId = entity.KeyId,
                                Role = roleCode
                            };
                            
                            jwtStr = JwtHelper.IssuerJwt(token);

                            #region 将当前登录用户写入Session
                            OperatorUser CurrentUser = new OperatorUser
                            {
                                KeyId = entity.KeyId,
                                EnCode = entity.EnCode,
                                AccountName = entity.AccountName,
                                Password = entity.Password,
                                NickName = entity.NickName,
                                RealName = entity.RealName,
                                Gender = entity.Gender,
                                Age = entity.Age,
                                Birthday = entity.Birthday,
                                MobilePhone = entity.MobilePhone,
                                AvatarUrl = entity.AvatarUrl,
                                Email = entity.Email,
                                WeChat = entity.WeChat,
                                Signature = entity.Signature,
                                IsAdmin = entity.IsAdmin,
                                IsLock = entity.IsLock,
                                LastLoginTime = DateTime.Now,
                                SignState = entity.SignState,
                            };
                            //写入Session
                            GlobalContext.SetCurrentUserInfo(CurrentUser);
                            #endregion

                            return jwtStr;
                        }
                        else
                        {
                            throw new Exception("密码错误，请重新输入");
                        }
                    }
                    else
                    {
                        throw new Exception("该用户被锁定，请联系管理员");
                    }
                }
                else
                {
                    throw new Exception("账户不存在，请重新输入");
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }
        }

        /// <summary>
        /// 根据账号密码 获取用户所属角色编码
        /// </summary>
        /// <param name = "loginName">登录账号</ param >
        /// < param name="loginPwd">登录密码</param>
        /// <returns></returns>
        public async Task<string> GetUserRoleName(string loginName, string loginPwd)
        {
            string roleCode = "";
            try
            {
                string pwd = EncryptProvider.Md5(loginPwd).ToLower();
                //查到符合条件的用户信息
                var user = await _repository.FindAsync(u => u.AccountName == loginName && u.Password == pwd);

                //查到角色列表
                var roleList = await _unitOfWork.GetDbClient().Queryable<RoleInfoEntity>().Where(r => r.IsDeleted == false && r.IsEnabled == true).ToListAsync();
                if (user != null)
                {
                    //查询用户角色中间表，获取用户角色信息
                    var userRoles = _unitOfWork.GetDbClient().Queryable<UserRoleEntity>().Where(ur=>ur.UserId == user.KeyId);
                    if (userRoles.CountAsync() != null)
                    {
                        var arr = userRoles.Select(ur => ur.RoleId).ToList();
                        var roles = roleList.Find(r => arr.Contains(r.KeyId));

                        roleCode = string.Join(",", roles.EnCode);
                    }
                }
                return roleCode;                
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        #region 弃用
        /// <summary>
        /// 登录 获取Token值
        /// </summary>
        /// <param name="accountname"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public async Task<string> CheckLogin(string accountname, string password)
        {
            try
            {
                var entity = await _repository.FindAsync(t => t.AccountName == accountname);
                if (entity != null)
                {
                    if (entity.IsEnabled == true && entity.IsLock == false)
                    {
                        //对输入的密码进行Md5加密
                        var pwd = EncryptProvider.Md5(password).ToLower();
                        if (entity.Password == pwd)
                        {
                            //登录成功 将用户信息加入Claim中
                            var authclaims = new[]
                            {
                                new Claim(JwtRegisteredClaimNames.Sub,entity.KeyId),//用户Id
                                new Claim(nameof(entity.EnCode),entity.EnCode),//编码/工号
                                new Claim(nameof(entity.NickName),entity.NickName),//昵称
                                new Claim(JwtRegisteredClaimNames.Name, entity.RealName),//真实姓名
                                new Claim(nameof(entity.AccountName),entity.AccountName),//登录账户
                                new Claim(JwtRegisteredClaimNames.Gender,entity.Gender.ToString()),//性别
                                new Claim(nameof(entity.Age),entity.Age.ToString()),//年龄
                                new Claim(JwtRegisteredClaimNames.Birthdate,Convert.ToDateTime(entity.Birthday).ToString("yyyy-MM-dd")),//出生日期
                                new Claim(ClaimTypes.MobilePhone,entity.MobilePhone),//手机号
                                new Claim(JwtRegisteredClaimNames.Email,entity.Email),//邮箱
                                new Claim(nameof(entity.WeChat),entity.WeChat),//微信号
                                new Claim(nameof(entity.Signature),entity.Signature),//个性签名
                                new Claim(nameof(entity.LastLoginTime),DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")),//最后登录时间
                                //注：这里不要存放敏感信息 例如密码等
                            };

                            #region 保存当前登录用户信息
                            var identity = new ClaimsIdentity(authclaims, Define.CurrentUserInfo);
                            var userPrincipal = new ClaimsPrincipal(identity);
                            #endregion


                            //签名秘钥 可以放到json文件中
                            var authKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(GlobalContext.AppSettingConfig.SecretKey));

                            var token = new JwtSecurityToken(
                                    issuer: GlobalContext.AppSettingConfig.Issuer,//Token的发行者
                                    audience: GlobalContext.AppSettingConfig.Audience,//Token的受理者
                                    expires: DateTime.Now.AddMinutes(30), //Token超时时间
                                    claims: authclaims,//用户信息加入认证
                                    signingCredentials: new SigningCredentials(authKey, SecurityAlgorithms.HmacSha256)
                                );

                            //获取Token值
                            var jwtToken = new JwtSecurityTokenHandler().WriteToken(token);

                            return jwtToken;
                        }
                        else
                        {
                            throw new Exception("密码错误，请重新输入");
                        }
                    }
                    else
                    {
                        throw new Exception("该用户被锁定，请联系管理员");
                    }
                }
                else
                {
                    throw new Exception("账户不存在，请重新输入");
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message.ToString());
            }
        }
        #endregion
        #endregion
    }
}
